package com.qfedu.fmmall.service.impl;

import com.fasterxml.jackson.databind.JavaType;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.qfedu.fmmall.dao.ProductImgMapper;
import com.qfedu.fmmall.dao.ProductMapper;
import com.qfedu.fmmall.dao.ProductParamsMapper;
import com.qfedu.fmmall.dao.ProductSkuMapper;
import com.qfedu.fmmall.entity.*;
import com.qfedu.fmmall.service.ProductService;
import com.qfedu.fmmall.utils.PageHelper;
import com.qfedu.fmmall.vo.ResultStatus;
import com.qfedu.fmmall.vo.ResultVo;
import lombok.val;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import tk.mybatis.mapper.entity.Example;

import java.io.IOException;
import java.util.*;

@Service
public class ProductServiceImpl implements ProductService {

    @Autowired
    private ProductMapper productMapper;

    @Autowired
    private ProductSkuMapper productSkuMapper;

    @Autowired
    private ProductImgMapper productImgMapper;

    @Autowired
    private ProductParamsMapper productParamsMapper;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private RestHighLevelClient restHighLevelClient;

    @Autowired
    private ObjectMapper objectMapper;

    @Override
    public ResultVo listRecommendProducts() {
        List<ProductVo> productVos = productMapper.selectProductByProductImg();
        ResultVo resultVo = new ResultVo(ResultStatus.OK, "success", productVos);
        return resultVo;
    }

    @Override
    public ResultVo getProductBatisInfo(String productId) {
        try {
            //1.去redis查看有没有这个数据
            String productInfo = (String) stringRedisTemplate.boundHashOps("products").get(productId);
            if (productInfo != null) {
                Product product = objectMapper.readValue(productInfo, Product.class);

                String productSku = (String)stringRedisTemplate.boundHashOps("productSku").get(productId);
                JavaType javaType1 = objectMapper.getTypeFactory().constructParametricType(ArrayList.class, ProductSku.class);
                List<ProductImg> SkuInfo = objectMapper.readValue(productSku, javaType1);

                String productImg = (String) stringRedisTemplate.boundHashOps("productImg").get(productId);
                JavaType javaType2 = objectMapper.getTypeFactory().constructParametricType(ArrayList.class, ProductImg.class);
                List<ProductImg> imgInfo = objectMapper.readValue(productImg, javaType2);

                //用HasMap拼接在一起
                HashMap<String, Object> map = new HashMap<>();
                map.put("Product", product);
                map.put("ProductSku", SkuInfo);
                map.put("ProductImg", imgInfo);

                return new ResultVo(ResultStatus.OK, "success", map);
            } else {
                //获取商品的数据
                Example example = new Example(Product.class);
                Example.Criteria criteria = example.createCriteria();
                criteria.andEqualTo("productId", productId);//根据id查找
                criteria.andEqualTo("productStatus", 1);//商品必须为上架状态
                List<Product> products = productMapper.selectByExample(example);
                String productInfos = objectMapper.writeValueAsString(products.get(0));

                stringRedisTemplate.boundHashOps("products").put(productId, productInfos);
                if (products.size() > 0) {
                    //获取商品的sku
                    Example example1 = new Example(ProductSku.class);
                    Example.Criteria criteria1 = example1.createCriteria();
                    criteria1.andEqualTo("productId", productId);
                    criteria1.andEqualTo("status", 1);
                    List<ProductSku> productSkus = productSkuMapper.selectByExample(example1);
                    String skuInfo = objectMapper.writeValueAsString(productSkus);
                    stringRedisTemplate.boundHashOps("productSku").put(productId, skuInfo);
                    //获取商品的图片
                    Example example2 = new Example(ProductImg.class);
                    Example.Criteria criteria2 = example2.createCriteria();
                    criteria2.andEqualTo("itemId", productId);
                    List<ProductImg> productImgs = productImgMapper.selectByExample(example2);
                    String imgInfo = objectMapper.writeValueAsString(productImgs);
                    stringRedisTemplate.boundHashOps("productImg").put(productId, imgInfo);

                    //用HasMap拼接在一起
                    HashMap<String, Object> map = new HashMap<>();
                    map.put("Product", products);
                    map.put("ProductSku", productSkus);
                    map.put("ProductImg", productImgs);


                    return new ResultVo(ResultStatus.OK, "success", map);
                } else {
                    return new ResultVo(ResultStatus.NO, "没有找到该商品", null);
                }
            }
        } catch (Exception e) {

        }
        return null;
    }


    @Override
    public ResultVo getProductBatisPrams(String productId) {
        Example example = new Example(ProductParams.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("productId",productId);

        List<ProductParams> productParams = productParamsMapper.selectByExample(example);
        if(productParams.size()>0){
            return new ResultVo(ResultStatus.OK,"success",productParams);
        }else{
            return new ResultVo(ResultStatus.NO,"该商品可能为三无产品",null);
        }
    }

    @Override
    public ResultVo getProductByCategoryId(int CategoryId, int pageNum, int limit) {
        //计算起始页
        int start = (pageNum - 1)*limit;
        List<ProductVo> productVos = productMapper.selectProductByCategoryId(CategoryId, start, limit);
        //计算数据总数
        Example example = new Example(Product.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("categoryId",CategoryId);
        int count = productMapper.selectCountByExample(example);
        //计算总页数
        int pageCount = count % limit == 0? count/limit : count/limit + 1;
        PageHelper<ProductVo> pageHelper = new PageHelper<>(count, pageCount, productVos);
        return new ResultVo(ResultStatus.OK,"SUCCESS",pageHelper);
    }

    @Override
    public ResultVo getBrandList(int categoryId) {
        List<String> list = productMapper.selectBrandByCategoryId(categoryId);
        return new ResultVo(ResultStatus.OK,"success",list);
    }

    @Override
    public ResultVo searchProductName(String keyword, int pageNum, int limit) {
        /**
         * 引入ES,优化搜索
         */
        ResultVo resultVo = null;
        try{
            //1.起始页
            int start = (pageNum-1)*limit;
            //2.从ES查询数据
            SearchRequest searchRequest = new SearchRequest("fmmallproductsindex");
            SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();

            //3.查询条件
            searchSourceBuilder.query(QueryBuilders.multiMatchQuery(keyword, "productName", "productSkuName"));
            //4.分页条件
            searchSourceBuilder.from(start);
            searchSourceBuilder.size(limit);

            //高亮显示
            HighlightBuilder highlightBuilder = new HighlightBuilder();
            HighlightBuilder.Field field1 = new HighlightBuilder.Field("productName");
            HighlightBuilder.Field field2 = new HighlightBuilder.Field("productSkuName");
            highlightBuilder.field(field1);
            highlightBuilder.field(field2);
            highlightBuilder.preTags("<label style='color:red'>");
            highlightBuilder.postTags("</label>");
            searchSourceBuilder.highlighter(highlightBuilder);
            searchRequest.source(searchSourceBuilder);

            //执行索引
            SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);

            //封装查询结果
            SearchHits hits = searchResponse.getHits();
            //获取总记录数
            int count = (int) (hits.getTotalHits().value);
            //计算总页数
            int pageCount = count%limit==0?count/limit:count/limit+1;
            Iterator<SearchHit> iterator = hits.iterator();
            List<Product4ES> products = new ArrayList<>();

            while (iterator.hasNext()){
                SearchHit searchHit = iterator.next();
                Product4ES product4ES = objectMapper.readValue(searchHit.getSourceAsString(), Product4ES.class);

                //获取高亮字段
                Map<String, HighlightField> highlightFields = searchHit.getHighlightFields();
                HighlightField highlightField1 = highlightFields.get("productName");
                if(highlightField1 != null){
                    String higLightProductName = Arrays.toString(highlightField1.fragments());
                    product4ES.setProductName(higLightProductName);
                }
                products.add(product4ES);
            }
            PageHelper<Product4ES> esPageHelper = new PageHelper<>(count, pageCount, products);
            resultVo = new ResultVo(ResultStatus.OK,"success",esPageHelper);

        }catch (IOException e){
            e.printStackTrace();
        }
        return resultVo;

        /**
         * 普通数据库查询
        int start = (pageNum - 1) * limit;
        keyword = "%"+keyword+"%";
        List<ProductVo> productVos = productMapper.SearchProductName(keyword, start, limit);

        //查询总个数
        Example example = new Example(Product.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andLike("productName",keyword);
        int count = productMapper.selectCountByExample(example);

        //总页数
        int pageCount = count%limit == 0 ? count/limit : count/limit + 1;

        PageHelper<ProductVo> pageHelper = new PageHelper<>(count, pageCount, productVos);
        ResultVo resultVo = new ResultVo(ResultStatus.OK, "success", pageHelper);

        return resultVo;
         **/
    }

    @Override
    public ResultVo searchBrand(String keyword) {
        keyword = "%"+keyword+"%";
        List<String> list = productMapper.selectBrandByKeyword(keyword);
        return new ResultVo(ResultStatus.OK,"success",list);
    }
}
